package com.fujimana.android.manacode.converter;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

import com.fujimana.android.manacode.converter.impl.CConverter;
import com.fujimana.android.manacode.converter.impl.CppConverter;
import com.fujimana.android.manacode.converter.impl.CsConverter;
import com.fujimana.android.manacode.converter.impl.JavaConverter;
import com.fujimana.android.manacode.converter.impl.JsConverter;
import com.fujimana.android.manacode.converter.impl.PHPConverter;
import com.fujimana.android.manacode.converter.impl.PerlConverter;
import com.fujimana.android.manacode.converter.impl.PythonConverter;
import com.fujimana.android.manacode.converter.impl.RubyConverter;
import com.fujimana.android.manacode.converter.impl.TextConverter;
import com.fujimana.android.manacode.converter.impl.VBConverter;

public class ConverterFactory {
	
	private static final ConverterFactory INSTANCE = new ConverterFactory();
	
	private Map<String, Class<? extends Converter>> converters;

	private ConverterFactory() {
		this.converters = new HashMap<String, Class<? extends Converter>>();
		
		this.converters.put("java", JavaConverter.class);
		this.converters.put("cpp", CppConverter.class);
		this.converters.put("c", CConverter.class);
		this.converters.put(".vb", VBConverter.class);
		this.converters.put("cs", CsConverter.class);
		this.converters.put("js", JsConverter.class);
		this.converters.put("php", PHPConverter.class);
		this.converters.put("perl", PerlConverter.class);
		this.converters.put("rb", RubyConverter.class);
		this.converters.put("py", PythonConverter.class);
	}

	public static ConverterFactory getInstance() {
		return INSTANCE;
	}
	
	public Converter getConverter(String type, Options options) {
		Converter converter = null;
		
		Class<? extends Converter> clazz = this.converters.get(type);
		if(clazz != null) {
			converter = instanceConverter(clazz, options);
		}
		
		if(converter == null) {
			converter = instanceDefaultConverter(options);
		}
		
		return converter;
	}
	
	@SuppressWarnings("rawtypes")
	private static Converter instanceConverter(Class<? extends Converter> clazz, Options options) {
		Converter converter = null;
		try {
			Constructor constructor = clazz.getConstructor(Options.class);
			converter = (Converter) constructor.newInstance(options);
		} catch (Exception e) {
			// nothing to do.
		}
		
		return converter;
	}
	
	private static Converter instanceDefaultConverter(Options options) {
		return new TextConverter(options);
	}
}
